#include <asm/system.h>
#include <linux/sched.h>
#include <linux/sem.h>
#include <asm/segment.h>

struct sem_inner
{
    char name[NAME_MAX];
    int value;
    struct task_struct *queue;
};


struct sem_inner sem_table[SEM_MAX_NUM];
sem_t sem_t_table[SEM_MAX_NUM];
sem_t error = {-1};
int current_num = 0;

sem_t* sys_sem_open(const char *name, unsigned int value)
{
    int i;
    char buffer[NAME_MAX];
    i = 0;
    while (get_fs_byte(name+i) != '\0')
    {
        buffer[i] = get_fs_byte(name+i);
        i++;
    }
    buffer[i] = '\0';
    

    // 寻找该信号量是否存在
    for (i = 0; i < current_num; i++)
    {
        if (strcmp(sem_table[i].name, buffer) == 0)
        {
            sem_t_table[i].index = i;
            return &sem_t_table[i];
        }
    }

    // 不存在，创建
    if (current_num + 1 < SEM_MAX_NUM)
    {
        strcpy(sem_table[current_num].name, buffer);
        sem_table[current_num].value = value;
        sem_t_table[current_num].index = current_num;
        current_num++;
        return &sem_t_table[current_num-1];
    }
    else
    {
        return &error;
    }
}

int sys_sem_wait(sem_t *sem)
{
    cli();

    while (sem_table[sem->index].value <= 0)
    {
        sleep_on(&sem_table[sem->index].queue);
    }
    sem_table[sem->index].value--;

    sti();

    return 1;
}

int sys_sem_post(sem_t *sem)
{
    cli();
    sem_table[sem->index].value++;
    if (sem_table[sem->index].queue)
    {
        wake_up(&sem_table[sem->index].queue);
    }

    sti();
    return 1;
}

int sys_sem_unlink(const char *name)
{
    struct sem_inner *result;
    int i;

    char buffer[NAME_MAX];
    i = 0;
    while (get_fs_byte(name+i) != '\0')
    {
        buffer[i] = get_fs_byte(name+i);
        i++;
    }
    buffer[i] = '\0';

    for (i = 0; i < current_num; i++)
    {
        if (strcmp(sem_table[i].name, buffer) == 0)
        {
            result = &sem_table[i];
            result->name[0] = '\0';
    		result->value = 0;
    		result->queue = 0x0;
    		break;
        }
    }

    return 1;
}
